#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <QUdpSocket>
#include<QRegularExpressionMatchIterator>
#include<QJsonObject>
#include<QDir>
#include<map>
#include<bitset>
#include<queue>

namespace lxj {
struct Node;
}

class UDPServer : public QUdpSocket
{
    Q_OBJECT
    enum ServerAction:int{
        LOGIN,      //登录业务
        LOGOUT,     //下线业务
        REGISTER,   //注册业务
        OTHER,      //其它业务
        NONE,       //无业务
        ERROR       //出现错误
    };
    struct msgStartInfo{
        int msgIndex;           //消息序号
        QHostAddress address;   //客户端地址
        ServerAction action;    //任务类型
        int startRelaPos;       //信息头在整个信息中的相对起始位置
        int endRelaPos;         //信息头在整个信息中的相对末尾位置

        msgStartInfo():msgIndex(-1),address(QHostAddress{}),action(ServerAction::NONE),startRelaPos(-1),endRelaPos(-1){}
    };
    struct msgEndInfo{
        int msgIndex;           //消息序号
        QHostAddress address;   //客户端地址
        int startRelaPos;       //信息尾在整个信息中的相对起始位置
        int endRelaPos;         //信息尾在整个信息中的相对末尾位置

        msgEndInfo():msgIndex(-1),address(QHostAddress{}),startRelaPos(-1),endRelaPos(-1){}
    };

public:
    static unsigned short m_id;

public:
    UDPServer();

signals:
    void MsgArrive(bool isArrive);

private:
    QUdpSocket *m_udpSocket;
    std::map<unsigned int,lxj::Node *> m_allNode;

//    QString receiveStr;
//    int shouldBeReceiveDataLen;

    std::queue<QString> msgQueue;
    std::queue<msgStartInfo *> msgHeadQueue;    //每句话头部信息队列
    std::queue<msgEndInfo *>   msgTailQueue;    //每句话尾部信息队列

private:
    //创建头部信息队列
    std::queue<msgStartInfo *> CreateStartStatusQueue(const QRegularExpressionMatchIterator& remi);
    //创建尾部信息队列
    std::queue<msgEndInfo *> CreateEndStatusQueue(const QRegularExpressionMatchIterator& remi);

    //解析头尾信息并将对应msg发给要处理的函数
    void sendMsgtoFunc(std::queue<msgStartInfo *>&& si, std::queue<msgEndInfo *>&& ei, const QString &c);

    //处理函数
    void mainProceFunc(const QString &msg,const ServerAction& action);
    void loginFunc(const QString &msg);
    void logoutFunc(const QString &msg);
    void registerFunc(const QString &msg);
    void otherFunc(const QString &msg);
    void errorFunc(const QString &msg);

private slots:
    void readPendingDatagrams();

    //收到数据后进行处理
    void doWorkOnMsg(bool isArrive);

};

namespace lxj {

//每个用户的信息
struct Node{
    unsigned int                    id;                 //被分配的id
    std::bitset<9>                  account;            //账号
    QString                         password;           //密码
    QDir                            head_portrait_dir;  //头像地址
    std::map<unsigned int,Node *>   friends;            //好友集合
};
}

#endif // UDPSERVER_H
